{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Title: #Alert Using Same Key-Card Three or More Times in a One Hour Period"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Difficulty: #Medium"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Category Title: #Algorithms"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tag Slug: #array #hash-table #string #sorting"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Name Translated: #数组 #哈希表 #字符串 #排序"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Solution Name: alertNames"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Translated Title: #警告一小时内使用相同员工卡大于等于三次的人"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Translated Content:\n",
    "<p>力扣公司的员工都使用员工卡来开办公室的门。每当一个员工使用一次他的员工卡，安保系统会记录下员工的名字和使用时间。如果一个员工在一小时时间内使用员工卡的次数大于等于三次，这个系统会自动发布一个 <strong>警告</strong>&nbsp;。</p>\n",
    "\n",
    "<p>给你字符串数组&nbsp;<code>keyName</code>&nbsp;和&nbsp;<code>keyTime</code> ，其中&nbsp;<code>[keyName[i], keyTime[i]]</code>&nbsp;对应一个人的名字和他在&nbsp;<strong>某一天</strong> 内使用员工卡的时间。</p>\n",
    "\n",
    "<p>使用时间的格式是 <strong>24小时制</strong>&nbsp;，形如<strong>&nbsp;\"HH:MM\"</strong>&nbsp;，比方说&nbsp;<code>\"23:51\"</code> 和&nbsp;<code>\"09:49\"</code>&nbsp;。</p>\n",
    "\n",
    "<p>请你返回去重后的收到系统警告的员工名字，将它们按 <strong>字典序</strong><strong>升序&nbsp;</strong>排序后返回。</p>\n",
    "\n",
    "<p>请注意&nbsp;<code>\"10:00\"</code> - <code>\"11:00\"</code>&nbsp;视为一个小时时间范围内，而&nbsp;<code>\"22:51\"</code> - <code>\"23:52\"</code>&nbsp;不被视为一小时时间范围内。</p>\n",
    "\n",
    "<p>&nbsp;</p>\n",
    "\n",
    "<p><strong>示例 1：</strong></p>\n",
    "\n",
    "<pre>\n",
    "<strong>输入：</strong>keyName = [\"daniel\",\"daniel\",\"daniel\",\"luis\",\"luis\",\"luis\",\"luis\"], keyTime = [\"10:00\",\"10:40\",\"11:00\",\"09:00\",\"11:00\",\"13:00\",\"15:00\"]\n",
    "<strong>输出：</strong>[\"daniel\"]\n",
    "<strong>解释：</strong>\"daniel\" 在一小时内使用了 3 次员工卡（\"10:00\"，\"10:40\"，\"11:00\"）。\n",
    "</pre>\n",
    "\n",
    "<p><strong>示例 2：</strong></p>\n",
    "\n",
    "<pre>\n",
    "<strong>输入：</strong>keyName = [\"alice\",\"alice\",\"alice\",\"bob\",\"bob\",\"bob\",\"bob\"], keyTime = [\"12:01\",\"12:00\",\"18:00\",\"21:00\",\"21:20\",\"21:30\",\"23:00\"]\n",
    "<strong>输出：</strong>[\"bob\"]\n",
    "<strong>解释：</strong>\"bob\" 在一小时内使用了 3 次员工卡（\"21:00\"，\"21:20\"，\"21:30\"）。\n",
    "</pre>\n",
    "\n",
    "<p>&nbsp;</p>\n",
    "\n",
    "<p><strong>提示：</strong></p>\n",
    "\n",
    "<ul>\n",
    "\t<li><code>1 &lt;= keyName.length, keyTime.length &lt;= 10<sup>5</sup></code></li>\n",
    "\t<li><code>keyName.length == keyTime.length</code></li>\n",
    "\t<li><code>keyTime</code> 格式为&nbsp;<strong>\"HH:MM\"&nbsp;</strong>。</li>\n",
    "\t<li>保证&nbsp;<code>[keyName[i], keyTime[i]]</code>&nbsp;形成的二元对&nbsp;<strong>互不相同&nbsp;</strong>。</li>\n",
    "\t<li><code>1 &lt;= keyName[i].length &lt;= 10</code></li>\n",
    "\t<li><code>keyName[i]</code>&nbsp;只包含小写英文字母。</li>\n",
    "</ul>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Description: [alert-using-same-key-card-three-or-more-times-in-a-one-hour-period](https://leetcode.cn/problems/alert-using-same-key-card-three-or-more-times-in-a-one-hour-period/description/)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Solutions: [alert-using-same-key-card-three-or-more-times-in-a-one-hour-period](https://leetcode.cn/problems/alert-using-same-key-card-three-or-more-times-in-a-one-hour-period/solutions/)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_cases = ['[\"daniel\",\"daniel\",\"daniel\",\"luis\",\"luis\",\"luis\",\"luis\"]\\n[\"10:00\",\"10:40\",\"11:00\",\"09:00\",\"11:00\",\"13:00\",\"15:00\"]', '[\"alice\",\"alice\",\"alice\",\"bob\",\"bob\",\"bob\",\"bob\"]\\n[\"12:01\",\"12:00\",\"18:00\",\"21:00\",\"21:20\",\"21:30\",\"23:00\"]']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        \n",
    "        d = defaultdict(list)\n",
    "        ans = set()\n",
    "        for kn, kt in zip(keyName, keyTime):\n",
    "            h, m = map(int, kt.split(\":\"))\n",
    "            t = h * 60 + m\n",
    "            d[kn].append(t)\n",
    "        \n",
    "        ans = set()\n",
    "        for name in d:\n",
    "            if len(d[name]) < 3: continue\n",
    "            time = sorted(d[name])\n",
    "            cnt = 0\n",
    "            for i in range(2, len(time)):\n",
    "                if time[i] - time[i-2] <= 60:\n",
    "                    ans.add(name)\n",
    "                    break\n",
    "\n",
    "        \n",
    "        return sorted(ans)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        ans = []\n",
    "        tmp = {}\n",
    "        for k, v in zip(keyName, keyTime):\n",
    "            if k not in tmp:\n",
    "                tmp[k] = []\n",
    "            tmp[k].append(v)\n",
    "        for k, v in tmp.items():\n",
    "            v.sort()\n",
    "            for i in range(len(v)-2):\n",
    "                st = int(v[i].split(':')[0]) * 60 + int(v[i].split(':')[1])\n",
    "                et = int(v[i+2].split(':')[0]) * 60 + int(v[i+2].split(':')[1])\n",
    "                if et - st <= 60 and k not in ans:\n",
    "                    ans.append(k)\n",
    "        ans.sort()\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        gb = collections.defaultdict(list)\n",
    "\n",
    "        def toM(t: str):\n",
    "            x, y = t.split(\":\")\n",
    "            return int(x) * 60 + int(y)\n",
    "\n",
    "        for i in range(len(keyName)):\n",
    "            gb[keyName[i]].append(keyTime[i])\n",
    "        ret = []\n",
    "        for k, v in gb.items():\n",
    "            v.sort()\n",
    "            for i in range(2, len(v)):\n",
    "                if toM(v[i]) - 60 <= toM(v[i - 2]):\n",
    "                    ret.append(k)\n",
    "                    break\n",
    "        ret.sort()\n",
    "        return ret"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        info = defaultdict(list)\n",
    "        n = len(keyName)\n",
    "        for i in range(n):\n",
    "            info[keyName[i]].append(keyTime[i])\n",
    "        res = []\n",
    "        for name, times in info.items():\n",
    "            if len(times) < 3:\n",
    "                continue\n",
    "            l = 0\n",
    "            r = 2\n",
    "            times.sort()\n",
    "            while r < len(times):\n",
    "                if times[l].split(\":\")[0] == times[r].split(\":\")[0]:\n",
    "                    res.append(name)\n",
    "                    break\n",
    "                elif int(times[l].split(\":\")[0]) + 1 == int(times[r].split(\":\")[0]):\n",
    "                    if times[r].split(\":\")[1] <= times[l].split(\":\")[1]:\n",
    "                        res.append(name)\n",
    "                        break\n",
    "                    else:\n",
    "                        l += 1\n",
    "                        r += 1\n",
    "                else:\n",
    "                    l += 1\n",
    "                    r += 1\n",
    "        res.sort()\n",
    "        return res\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        def getTime(hh, mm):\n",
    "            return int(hh) * 60 + int(mm)\n",
    "        d = dict()\n",
    "        for i in range(len(keyName)):\n",
    "            r = d.get(keyName[i], [])\n",
    "            r.append(keyTime[i])\n",
    "            d[keyName[i]] = r\n",
    "        result = []\n",
    "        for name, time in d.items():\n",
    "            time = sorted(time)\n",
    "            if len(time) <= 2:\n",
    "                continue\n",
    "            for i in range(0, len(time)):\n",
    "                if i + 2 >= len(time):\n",
    "                    break\n",
    "                ed = getTime(time[i+2][0:2], time[i+2][3:5])\n",
    "                st = getTime(time[i][0:2], time[i][3:5])\n",
    "                if ed - st <= 60:\n",
    "                    result.append(name)\n",
    "                    break\n",
    "                \n",
    "        result = sorted(result)\n",
    "        return result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from functools import cmp_to_key\n",
    "from collections import defaultdict\n",
    "\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName, keyTime):\n",
    "        dict1 = defaultdict(list)\n",
    "        for x, y in enumerate(keyName):\n",
    "            dict1[y].append(keyTime[x])\n",
    "        for i in dict1:\n",
    "            dict1[i].sort()\n",
    "\n",
    "        list2 = []\n",
    "        for i in dict1:\n",
    "            list1 = dict1[i]\n",
    "            r = 0\n",
    "            l = 2\n",
    "            while l <= len(list1)-1:\n",
    "                x, y = list(map(int, list1[r].split(\":\")))\n",
    "                m, n = list(map(int, list1[l].split(\":\")))\n",
    "                if m == x:\n",
    "                    list2.append(i)\n",
    "                    break\n",
    "                elif (m-x == 1 and y >= n):\n",
    "                    list2.append(i)\n",
    "                    break\n",
    "                else:\n",
    "                    r += 1\n",
    "                    l += 1\n",
    "        list2.sort()\n",
    "        return list2\n",
    "\n",
    "\n",
    "a = [\"alice\",\"alice\",\"alice\",\"bob\",\"bob\",\"bob\",\"bob\"]\n",
    "b = [\"12:01\",\"12:00\",\"18:00\",\"21:00\",\"21:20\",\"21:30\",\"23:00\"]\n",
    "Solution().alertNames(a, b)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        dct = collections.defaultdict(list)\n",
    "\n",
    "        for n, t in zip(keyName, keyTime):\n",
    "            dct[n].append(t)\n",
    "\n",
    "        res = []\n",
    "        for k, vals in dct.items():\n",
    "            n = len(vals)\n",
    "            if n < 3:\n",
    "                continue\n",
    "\n",
    "            vals.sort()\n",
    "            for i in range(2, n):\n",
    "                pre = list(map(int, vals[i-2].split(\":\")))\n",
    "                now = list(map(int, vals[i].split(\":\")))\n",
    "                # print(k)\n",
    "                # print(pre)\n",
    "                # print(now)\n",
    "                # print(now[0] * 60 + now[1])\n",
    "                # print(pre[0] * 60 + pre[1])\n",
    "                # print(now[0] * 60 + now[1] - pre[0] * 60 - pre[1])\n",
    "\n",
    "                if now[0] * 60 + now[1] - pre[0] * 60 - pre[1] <= 60:\n",
    "                    # print(\"----------\")\n",
    "                    res.append(k)\n",
    "                    # print(res)\n",
    "                    # print(res.sort())\n",
    "                    break\n",
    "\n",
    "\n",
    "        return sorted(res)\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames1(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        timeMap = defaultdict(list)\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            hour, minute = int(time[:2]), int(time[3:])\n",
    "            timeMap[name].append(hour * 60 + minute)\n",
    "\n",
    "        ans = []\n",
    "        for name, times in timeMap.items():\n",
    "            times.sort()\n",
    "            if any(t2 - t1 <= 60 for t1, t2 in zip(times, times[2:])):\n",
    "                ans.append(name)\n",
    "\n",
    "        ans.sort()\n",
    "        return ans\n",
    "\n",
    "\n",
    "\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        dct = collections.defaultdict(list)\n",
    "\n",
    "        for n, t in zip(keyName, keyTime):\n",
    "            dct[n].append(t)\n",
    "\n",
    "        res = []\n",
    "        for k, vals in dct.items():\n",
    "            n = len(vals)\n",
    "            if n < 3:\n",
    "                continue\n",
    "\n",
    "            vals.sort()\n",
    "            for i in range(2, n):\n",
    "                pre = list(map(int, vals[i-2].split(\":\")))\n",
    "                now = list(map(int, vals[i].split(\":\")))\n",
    "\n",
    "                if now[0] * 60 + now[1] - pre[0] * 60 - pre[1] <= 60:\n",
    "                    res.append(k)\n",
    "                    break\n",
    "\n",
    "\n",
    "        return sorted(res)\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        res = []\n",
    "        hashmap = collections.defaultdict(list)\n",
    "        n = len(keyName)\n",
    "        for i in range(n):\n",
    "            hashmap[keyName[i]].append(keyTime[i])\n",
    "        for name, lst in hashmap.items():\n",
    "            if len(lst) < 3:\n",
    "                continue\n",
    "            lst.sort()\n",
    "            for i in range(2, len(lst)):\n",
    "                time1 = int(lst[i][0:2]) * 60 + int(lst[i][3:5]) \n",
    "                time2 = int(lst[i - 2][0:2]) * 60 + int(lst[i - 2][3:5]) \n",
    "                if time1 - time2 <= 60:\n",
    "                    res.append(name)\n",
    "                    break\n",
    "        return sorted(res)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        cnt=collections.defaultdict(list)\n",
    "\n",
    "        for name,time in zip(keyName,keyTime):\n",
    "            cnt[name].append(time)\n",
    "        ans=[]\n",
    "    \n",
    "        def check(a,b):\n",
    "\n",
    "            ha=int(a[:2])\n",
    "            hb=int(b[:2])\n",
    "            ma=int(a[3:])\n",
    "            mb=int(b[3:])\n",
    "            ha=ha+1\n",
    "            print(ha,hb,ma,mb)\n",
    "            if ha >hb:\n",
    "                return True\n",
    "            elif ha==hb:\n",
    "                if ma>=mb:\n",
    "                    return True\n",
    "            return False\n",
    "       # print(check(\"17:44\",\"18:48\"))\n",
    "       # print(cnt)\n",
    "      #  return []\n",
    "\n",
    "        for x in cnt:\n",
    "            arr=sorted(cnt[x])\n",
    "            print(arr)\n",
    "            n=len(arr)\n",
    "            for i,v in enumerate(arr):\n",
    "                t=i+2\n",
    "                if t<=n-1:\n",
    "                    if check(arr[i],arr[t]):\n",
    "                        ans.append(x)\n",
    "                        break\n",
    "        \n",
    "        return sorted(ans)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        n=len(keyName)\n",
    "        d=defaultdict(list)\n",
    "        for i in range(n):\n",
    "            keyTime[i]=int(keyTime[i][:2]+keyTime[i][3:])\n",
    "            d[keyName[i]].append(keyTime[i])\n",
    "        ans=[]\n",
    "        for i in d:\n",
    "            k=sorted(d[i])\n",
    "            n=len(k)\n",
    "            if n<3:\n",
    "                break\n",
    "            for j in range(n-2):\n",
    "                if k[j+2]-k[j]<=100:\n",
    "                    ans.append(i)\n",
    "                    break\n",
    "        return sorted(ans)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "\n",
    "        def HourToMinute(curTime: str ) -> int:\n",
    "            hour_minute = curTime.split(\":\")\n",
    "            hour, minute = hour_minute[0], hour_minute[1]\n",
    "            return int(hour) * 60 + int(minute)\n",
    "\n",
    "        dic = {}\n",
    "        res = set()\n",
    "        \n",
    "        # print(HourToMinute(\"21:00\"))\n",
    "        for i in range(len(keyName)):\n",
    "            if keyName[i] not in dic:\n",
    "                dic[keyName[i]] = [keyTime[i]]\n",
    "            else:\n",
    "                dic[keyName[i]].append(keyTime[i])\n",
    "\n",
    "        for name, times in dic.items():\n",
    "            times.sort()\n",
    "            for i in range(0, len(times) -2):\n",
    "                if HourToMinute(times[i+2]) - HourToMinute(times[i]) <= 60:\n",
    "                    res.add(name)\n",
    "\n",
    "        return sorted(res)\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "        # initialize the dic\n",
    "        # initialize the res to keep track of the name that gets warning \n",
    "            \n",
    "        # use dic to keep track of the time {key: string, value: list of time}\n",
    "            # if we don't have the keyName, we put this in the dic\n",
    "            # else: we loop through all the keyTime in the list, and see if we have \n",
    "                # abs(keyTime - curTime) <= 60 \n",
    "                    # append to res\n",
    "        \n",
    "        # when we return the res, don't forget to sort it \n",
    "            \n",
    "            \n",
    "            # we also want to write a functio to convert the time: input \"HH:MM\",\n",
    "            # and we are returning the time in minute \n",
    "            # intput: keyTime: string  output: convertedTime: int\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "\n",
    "        def HourToMinute(curTime: str ) -> int:\n",
    "            hour_minute = curTime.split(\":\")\n",
    "            hour, minute = hour_minute[0], hour_minute[1]\n",
    "            return int(hour) * 60 + int(minute)\n",
    "\n",
    "        dic = {}\n",
    "        res = set()\n",
    "        \n",
    "        # print(HourToMinute(\"21:00\"))\n",
    "        for i in range(len(keyName)):\n",
    "            if keyName[i] not in dic:\n",
    "                dic[keyName[i]] = [keyTime[i]]\n",
    "            else:\n",
    "                dic[keyName[i]].append(keyTime[i])\n",
    "\n",
    "        for name, times in dic.items():\n",
    "            times.sort()\n",
    "            for i in range(0, len(times) -2):\n",
    "                if HourToMinute(times[i+2]) - HourToMinute(times[i]) <= 60:\n",
    "                    res.add(name)\n",
    "\n",
    "        res = list(res)\n",
    "        res.sort()\n",
    "        return res\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "        # initialize the dic\n",
    "        # initialize the res to keep track of the name that gets warning \n",
    "            \n",
    "        # use dic to keep track of the time {key: string, value: list of time}\n",
    "            # if we don't have the keyName, we put this in the dic\n",
    "            # else: we loop through all the keyTime in the list, and see if we have \n",
    "                # abs(keyTime - curTime) <= 60 \n",
    "                    # append to res\n",
    "        \n",
    "        # when we return the res, don't forget to sort it \n",
    "            \n",
    "            \n",
    "            # we also want to write a functio to convert the time: input \"HH:MM\",\n",
    "            # and we are returning the time in minute \n",
    "            # intput: keyTime: string  output: convertedTime: int\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "\n",
    "        def inOneHour(start: str, now: str) -> bool:\n",
    "            if int(now[:2]) == int(start[:2]):\n",
    "                return True\n",
    "            if int(now[:2]) - int(start[:2]) == 1:\n",
    "                if 60 - int(start[3:]) + int(now[3:]) <= 60:\n",
    "                    return True\n",
    "            return False\n",
    "        \n",
    "        n = len(keyName)\n",
    "        d = dict()\n",
    "        res = []\n",
    "        for i in range(n):\n",
    "            if keyName[i] not in d:\n",
    "                d[keyName[i]] = [keyTime[i]]\n",
    "            else:\n",
    "                d[keyName[i]].append(keyTime[i])\n",
    "        for key in d.keys():\n",
    "            d[key].sort()\n",
    "            if len(d[key]) >= 3:\n",
    "                for i in range(len(d[key]) - 2):\n",
    "                    if inOneHour(d[key][i], d[key][i + 2]):\n",
    "                        res.append(key)\n",
    "                        break\n",
    "        res.sort()\n",
    "        return res\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        timeMap = defaultdict(list)\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            hour, minute = int(time[:2]), int(time[3:])\n",
    "            timeMap[name].append(hour * 60 + minute)\n",
    "\n",
    "        ans = []\n",
    "        for name, times in timeMap.items():\n",
    "            times.sort()\n",
    "            if any(t2 - t1 <= 60 for t1, t2 in zip(times, times[2:])):\n",
    "                ans.append(name)\n",
    "        ans.sort()\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        timeMap = defaultdict(list)\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            hour, minute = int(time[:2]), int(time[3:])\n",
    "            timeMap[name].append(hour * 60 + minute)\n",
    "\n",
    "        ans = []\n",
    "        for name, times in timeMap.items():\n",
    "            times.sort()\n",
    "            if any(t2 - t1 <= 60 for t1, t2 in zip(times, times[2:])):\n",
    "                ans.append(name)\n",
    "        ans.sort()\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from collections import defaultdict\n",
    "from bisect import bisect_left\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        cnt = defaultdict(list)\n",
    "        res = set()\n",
    "        n = len(keyName)\n",
    "        for i in range(n):\n",
    "            name,time = keyName[i],keyTime[i]\n",
    "            if name in res:\n",
    "                continue\n",
    "            t = self.tomin(time)\n",
    "            idx = bisect_left(cnt[name], t)\n",
    "            cnt[name].insert(idx, t)\n",
    "            if len(cnt[name])-idx>=3:\n",
    "                if cnt[name][idx+2] - t<=60:\n",
    "                    res.add(name)\n",
    "            if idx>=2:\n",
    "                if t - cnt[name][idx-2]<=60:\n",
    "                    res.add(name)\n",
    "            if idx>=1 and idx<len(cnt[name])-1:\n",
    "                if cnt[name][idx+1]-cnt[name][idx-1]<=60:\n",
    "                    res.add(name)\n",
    "            pass\n",
    "        res = list(res)\n",
    "        res.sort()\n",
    "        return res\n",
    "\n",
    "    def tomin(self, text:str):\n",
    "        return int(text[:2])*60 + int(text[3:])\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        timeMap = defaultdict(list)\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            hour, minute = int(time[:2]), int(time[3:])\n",
    "            timeMap[name].append(hour * 60 + minute)\n",
    "\n",
    "        ans = []\n",
    "        for name, times in timeMap.items():\n",
    "            times.sort()\n",
    "            if any(t2 - t1 <= 60 for t1, t2 in zip(times, times[2:])):\n",
    "                ans.append(name)\n",
    "\n",
    "        ans.sort()\n",
    "        return ans\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        d = defaultdict(list)\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            d[name].append(int(time[:2]) * 60 + int(time[3:]))\n",
    "\n",
    "        ans = set()\n",
    "        for name, time in d.items():\n",
    "            time.sort()\n",
    "            n = len(time)\n",
    "            if n < 3:\n",
    "                continue\n",
    "            for i in range(n - 2):\n",
    "                if time[i + 2] - time[i] <= 60:\n",
    "                    ans.add(name)\n",
    "        return sorted(ans)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        d = defaultdict(list)\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            d[name].append(int(time[:2]) * 60 + int(time[-2:]))\n",
    "\n",
    "        ans = set()\n",
    "        for name, time in d.items():\n",
    "            time.sort()\n",
    "            n = len(time)\n",
    "            if n < 3:\n",
    "                continue\n",
    "            for i in range(n - 2):\n",
    "                if time[i + 2] - time[i] <= 60:\n",
    "                    ans.add(name)\n",
    "        return sorted(ans)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        count = defaultdict(list)\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            hour, minute = list(map(int, time.split(':')))\n",
    "            count[name].append(hour*60+minute)\n",
    "        ans = set()\n",
    "        for key, val in count.items():\n",
    "            count[key].sort()\n",
    "            for i in range(len(val)-2):\n",
    "                if count[key][i+2]-count[key][i] <= 60:\n",
    "                    ans.add(key)\n",
    "        return sorted(ans)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        timeMap = defaultdict(list)\n",
    "        for n, t in zip(keyName, keyTime):\n",
    "            t = t.split(':')\n",
    "            hh, mm = int(t[0]), int(t[1])\n",
    "            timeMap[n].append(hh * 60 + mm)\n",
    "        \n",
    "        res = set()\n",
    "        for n, tl in timeMap.items():\n",
    "            tl = sorted(tl)\n",
    "            if any(t1 - t2 <= 60 for t1, t2 in zip(tl[2:], tl)):\n",
    "                res.add(n)\n",
    "        \n",
    "        return sorted(list(res))\n",
    "    \n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        people = defaultdict(list)\n",
    "        def hour_to_minutes(string):\n",
    "            hour, minutes = string.split(':')\n",
    "            return int(hour) * 60 + int(minutes)\n",
    "        for idx, val in enumerate(keyName):\n",
    "            people[val].append(hour_to_minutes(keyTime[idx]))\n",
    "        res = []\n",
    "        for k, v in people.items():\n",
    "            cnt = 0\n",
    "            v.sort()\n",
    "            left = 0\n",
    "            for idx in range(1,len(v)-1):\n",
    "                if v[idx] - v[left]<=60 and v[idx+1] - v[left] <= 60:\n",
    "                    res.append(k)\n",
    "                    break\n",
    "                else:\n",
    "                    left += 1\n",
    "        res.sort()\n",
    "        return res\n",
    "                \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        timeMap = defaultdict(list)\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            hour, minute = int(time[:2]), int(time[3:])\n",
    "            timeMap[name].append(hour * 60 + minute)\n",
    "\n",
    "        ans = []\n",
    "        for name, times in timeMap.items():\n",
    "            times.sort()\n",
    "            if any(t2 - t1 <= 60 for t1, t2 in zip(times, times[2:])):\n",
    "                ans.append(name)\n",
    "        ans.sort()\n",
    "        return ans\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        \n",
    "        timeMap = defaultdict(list)\n",
    "\n",
    "        for name,time in zip(keyName,keyTime):\n",
    "            hour,minute = int(time[:2]),int(time[3:])\n",
    "            timeMap[name].append(hour*60+minute)\n",
    "        \n",
    "        ans = []\n",
    "        for name,times in timeMap.items():\n",
    "            times.sort()\n",
    "            if any(t2-t1 <= 60 for t1, t2 in zip(times,times[2:])):\n",
    "                ans.append(name)\n",
    "        ans.sort()\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        d = defaultdict(list)\n",
    "        for time, name in zip(keyTime, keyName):\n",
    "            time = int(time[:2]) * 60 + int(time[3:])\n",
    "            d[name].append(time)\n",
    "\n",
    "        ans = []\n",
    "        for name, times in d.items():\n",
    "            times.sort()\n",
    "            for i in range(2, len(times)):\n",
    "                if times[i] - times[i - 2] <= 60:\n",
    "                    ans.append(name)\n",
    "                    break\n",
    "        \n",
    "        ans.sort()\n",
    "        return ans\n",
    "            \n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        n = len(keyName)\n",
    "        ans,d = [], defaultdict(list)\n",
    "        for i in range(n):\n",
    "            h,m = map(int, keyTime[i].split(':'))\n",
    "            timestamp = h*60+m\n",
    "            d[keyName[i]].append(timestamp)\n",
    "        for name, times in d.items():\n",
    "            times.sort()\n",
    "            if any(t2 - t1 <= 60 for t1, t2 in zip(times, times[2:])):\n",
    "                ans.append(name)\n",
    "        return sorted(ans)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        d = defaultdict(list)\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            d[name].append(int(time[:2]) * 60 + int(time[3:]))\n",
    "\n",
    "        ans = set()\n",
    "        for name, time in d.items():\n",
    "            time.sort()\n",
    "            n = len(time)\n",
    "            if n < 3:\n",
    "                continue\n",
    "            for i in range(n - 2):\n",
    "                if time[i + 2] - time[i] <= 60:\n",
    "                    ans.add(name)\n",
    "        return sorted(ans)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        d = defaultdict(list)\n",
    "        for name, t in zip(keyName, keyTime):\n",
    "            t = int(t[:2]) * 60 + int(t[3:])\n",
    "            d[name].append(t)\n",
    "        ans = []\n",
    "        for name, ts in d.items():\n",
    "            if (n := len(ts)) > 2:\n",
    "                ts.sort()\n",
    "                for i in range(n - 2):\n",
    "                    if ts[i + 2] - ts[i] <= 60:\n",
    "                        ans.append(name)\n",
    "                        break\n",
    "        ans.sort()\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        # 哈希表+排序\n",
    "            # 哈希表+排序\n",
    "            hashmap = collections.defaultdict(list)\n",
    "            for k, t in zip(keyName, keyTime):\n",
    "                hashmap[k].append(int(t[:2]) * 60 + int(t[-2:]))\n",
    "            ans = []\n",
    "            for k, t_list in hashmap.items():\n",
    "                if len(t_list) < 3: continue\n",
    "                t_list.sort()\n",
    "                n=len(t_list)\n",
    "                for i in range(n - 2):\n",
    "                    if t_list[i + 2] - t_list[i] <= 60:\n",
    "                        ans.append(k)\n",
    "                        break\n",
    "            ans.sort()\n",
    "            return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        d = defaultdict(list)\n",
    "        for name, t in zip(keyName, keyTime):\n",
    "            t = int(t[:2]) * 60 + int(t[3:])\n",
    "            d[name].append(t)\n",
    "        ans = []\n",
    "        for name, ts in d.items():\n",
    "            if (n := len(ts)) > 2:\n",
    "                ts.sort()\n",
    "                for i in range(n - 2):\n",
    "                    if ts[i + 2] - ts[i] <= 60:\n",
    "                        ans.append(name)\n",
    "                        break\n",
    "        ans.sort()\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        mapping = {}\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            if(name not in mapping):\n",
    "                mapping[name] = []\n",
    "            h, m = time.split(':')\n",
    "            mapping[name].append(int(h)*60+int(m))\n",
    "        result = []\n",
    "        for name in mapping:\n",
    "            if(len(mapping[name]) < 3):\n",
    "                continue\n",
    "            times = sorted(mapping[name])\n",
    "            for i in range(len(times)-2):\n",
    "                if(times[i+2] - times[i] <= 60):\n",
    "                    result.append(name)\n",
    "                    break\n",
    "        return sorted(result)\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        d = defaultdict(list)\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            d[name].append(int(time[:2] + time[3:]))\n",
    "\n",
    "        ans = set()\n",
    "        for name, time in d.items():\n",
    "            time.sort()\n",
    "            n = len(time)\n",
    "            if n < 3:\n",
    "                continue\n",
    "            for i in range(n - 2):\n",
    "                if time[i + 2] - time[i] <= 100:\n",
    "                    ans.add(name)\n",
    "        return sorted(ans)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        mapping = {}\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            if(name not in mapping):\n",
    "                mapping[name] = []\n",
    "            h, m = time.split(':')\n",
    "            mapping[name].append(int(h)*60+int(m))\n",
    "        result = []\n",
    "        for name in mapping:\n",
    "            if(len(mapping[name]) < 3):\n",
    "                continue\n",
    "            times = sorted(mapping[name])\n",
    "            for i in range(len(times)-2):\n",
    "                if(times[i+2] - times[i] <= 60):\n",
    "                    result.append(name)\n",
    "                    break\n",
    "        return sorted(result)\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        dic = defaultdict(list)\n",
    "        ans = []\n",
    "        for i in range(len(keyName)):\n",
    "            time = int(keyTime[i][:2]) * 60 + int(keyTime[i][3:])\n",
    "            dic[keyName[i]].append(time)\n",
    "        for j in dic.keys():\n",
    "            if len(dic[j]) >= 3:\n",
    "                dic[j].sort()\n",
    "                for k in range(len(dic[j])-2):\n",
    "                    if dic[j][k+2] - dic[j][k] <= 60:\n",
    "                        ans.append(j)\n",
    "                        break\n",
    "        return sorted(ans)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        d = defaultdict(list)\n",
    "        for time, name in zip(keyTime, keyName):\n",
    "            time = int(time[:2]) * 60 + int(time[3:])\n",
    "            d[name].append(time)\n",
    "\n",
    "        ans = []\n",
    "        for name, times in d.items():\n",
    "            times.sort()\n",
    "            for i in range(2, len(times)):\n",
    "                if times[i] - times[i - 2] <= 60:\n",
    "                    ans.append(name)\n",
    "                    break\n",
    "        \n",
    "        return sorted(ans)\n",
    "            \n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        user_d = {}\n",
    "        n = len(keyName)\n",
    "        def int_time(time):\n",
    "            hour_,minute_ = time.split(':')\n",
    "            hour_,minute_ = int(hour_),int(minute_)\n",
    "            return hour_*60+minute_\n",
    "        for i in range(n):\n",
    "            if keyName[i] not in user_d:\n",
    "                user_d[keyName[i]] = []\n",
    "            cur_time = int_time(keyTime[i])\n",
    "            user_d[keyName[i]].append(cur_time)\n",
    "            # if cur_time <= 60:\n",
    "                # user_d[keyName[i]].append(cur_time + 24*60)\n",
    "        for name in user_d.keys():\n",
    "            user_d[name].sort()\n",
    "        res = []\n",
    "        for name,lst in user_d.items():\n",
    "            if len(lst) <= 2:\n",
    "                continue\n",
    "            start_idx = 0\n",
    "            start_time = lst[0]\n",
    "            cur_cnt = 1\n",
    "            for t in lst[1:]:\n",
    "                while t - start_time > 60:\n",
    "                    \n",
    "                    start_idx += 1\n",
    "                    # print(lst,t,start_time,start_idx)\n",
    "                    start_time = lst[start_idx]\n",
    "                    cur_cnt -= 1\n",
    "                cur_cnt += 1\n",
    "                # print(f'name = {name},cur_time = {t}, start time = {start_time}, cur cnt = {cur_cnt}')\n",
    "                if cur_cnt == 3:\n",
    "                    # print('hello ?')\n",
    "                    res.append(name)\n",
    "                    break\n",
    "        # print(res)\n",
    "        res.sort()\n",
    "        # print(res)\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        ret = []\n",
    "        dic = defaultdict(list)\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            # print(name, time)\n",
    "            time_min = int(time[:2]) * 60 + int(time[3:])\n",
    "            dic[name].append(time_min)\n",
    "        # print(dic)\n",
    "\n",
    "        for m, n in dic.items():\n",
    "            # print(n)\n",
    "            if (l := len(n)) > 2:\n",
    "                n.sort()\n",
    "                # for i in n:\n",
    "                #     # print(i)\n",
    "                for i in range(l - 2):\n",
    "                    if n[i + 2] - n[i] <= 60:\n",
    "                        # print(n[i + 2],n[i])\n",
    "                        ret.append(m)\n",
    "                        break\n",
    "        # print(ret)\n",
    "        ret.sort()\n",
    "        return ret"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        cnt = defaultdict(list)\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            cnt[name].append(int(time[:2]) * 60 + int(time[3:]))\n",
    "        ret = []\n",
    "        for k, v in cnt.items():\n",
    "            v.sort()\n",
    "            if len(v) >= 3:\n",
    "                for i in range(2, len(v)):\n",
    "                    if 0 < v[i] - v[i-2] <= 60:\n",
    "                        ret.append(k)\n",
    "                        break\n",
    "        ret.sort()\n",
    "        return ret"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        mapping = {}\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            if(name not in mapping):\n",
    "                mapping[name] = []\n",
    "            h, m = time.split(':')\n",
    "            mapping[name].append(int(h)*60+int(m))\n",
    "        result = []\n",
    "        for name in mapping:\n",
    "            if(len(mapping[name]) < 3):\n",
    "                continue\n",
    "            times = sorted(mapping[name])\n",
    "            for i in range(len(times)-2):\n",
    "                if(times[i+2] - times[i] <= 60):\n",
    "                    result.append(name)\n",
    "                    break\n",
    "        return sorted(result)\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        d = defaultdict(list)\n",
    "        for time, name in zip(keyTime, keyName):\n",
    "            time = int(time[:2]) * 60 + int(time[3:])\n",
    "            d[name].append(time)\n",
    "\n",
    "        ans = []\n",
    "        for name, times in d.items():\n",
    "            times.sort()\n",
    "            for i in range(2, len(times)):\n",
    "                if times[i] - times[i - 2] <= 60:\n",
    "                    ans.append(name)\n",
    "                    break\n",
    "        \n",
    "        return sorted(ans)\n",
    "            \n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        mapping = {}\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            if(name not in mapping):\n",
    "                mapping[name] = []\n",
    "            h, m = time.split(':')\n",
    "            mapping[name].append(int(h)*60+int(m))\n",
    "        result = []\n",
    "        for name in mapping:\n",
    "            if(len(mapping[name]) < 3):\n",
    "                continue\n",
    "            times = sorted(mapping[name])\n",
    "            for i in range(len(times)-2):\n",
    "                if(times[i+2] - times[i] <= 60):\n",
    "                    result.append(name)\n",
    "                    break\n",
    "        return sorted(result)\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        cnt = defaultdict(list)\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            cnt[name].append(int(time[:2]) * 60 + int(time[3:]))\n",
    "        ret = []\n",
    "        for k, v in cnt.items():\n",
    "            if len(v) >= 3:\n",
    "                v.sort()\n",
    "                for i in range(2, len(v)):\n",
    "                    if 0 < v[i] - v[i-2] <= 60:\n",
    "                        ret.append(k)\n",
    "                        break\n",
    "        ret.sort()\n",
    "        return ret"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        mp = defaultdict(list)\n",
    "        for name, t in zip(keyName, keyTime):\n",
    "            t = int(t[:2]) * 60 + int(t[3:])\n",
    "            mp[name].append(t)\n",
    "        ans = []\n",
    "        for name, t in mp.items():\n",
    "            if len(t) > 2:\n",
    "                t.sort()\n",
    "                for i in range(len(t) - 2):\n",
    "                    if t[i + 2] - t[i] <= 60:\n",
    "                        ans.append(name)\n",
    "                        break\n",
    "        ans.sort()\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        member = defaultdict(list)\n",
    "\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            hour, minute = int(time[:2]), int(time[3:])\n",
    "            member[name].append(hour * 60 + minute)\n",
    "\n",
    "        res = []\n",
    "        for k, v in member.items():\n",
    "            v.sort(key=float)\n",
    "            if any(t2 - t1 <= 60 for t1, t2 in zip(v, v[2:])):\n",
    "                res.append(k)\n",
    "        return sorted(res)\n",
    "        \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        record = defaultdict(list)\n",
    "        n = len(keyName)\n",
    "        max_allowed_times = 3\n",
    "        unique_names = []\n",
    "\n",
    "        for i in range(n):\n",
    "            name, time = keyName[i], keyTime[i]\n",
    "            hour, minute = int(time[:2]), int(time[3:])\n",
    "            record[name].append(hour * 60 + minute)\n",
    "            \n",
    "        for name, times in record.items():\n",
    "            if len(times) < max_allowed_times:\n",
    "                continue\n",
    "            \n",
    "            times.sort()\n",
    "            if any(t2 - t1 <= 60 for t1, t2 in zip(times, times[2:])):\n",
    "                unique_names.append(name)\n",
    "                \n",
    "        unique_names.sort()\n",
    "        return unique_names\n",
    "                \n",
    "            \n",
    "            \n",
    "            \n",
    "                "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def __isIn1Hour(self, timeA, timeB):\n",
    "        hour_diff = int(timeB[0: 2]) - int(timeA[0: 2])\n",
    "        minute_diff = int(timeB[3: 5]) - int(timeA[3: 5])\n",
    "\n",
    "        if  hour_diff == 0:\n",
    "            return True\n",
    "\n",
    "        if hour_diff >= 2:\n",
    "            return False\n",
    "\n",
    "        return minute_diff <= 0\n",
    "\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        record = defaultdict(list)\n",
    "        n = len(keyName)\n",
    "        max_allowed_times = 3\n",
    "        unique_names = []\n",
    "\n",
    "\n",
    "        for i in range(n):\n",
    "            name, time = keyName[i], keyTime[i]\n",
    "            hour, minute = int(time[:2]), int(time[3:])\n",
    "            record[name].append(hour * 60 + minute)\n",
    "            \n",
    "        for name, times in record.items():\n",
    "            if len(times) < 3:\n",
    "                continue\n",
    "            \n",
    "            times.sort()\n",
    "            if any(t2 - t1 <= 60 for t1, t2 in zip(times, times[2:])):\n",
    "                unique_names.append(name)\n",
    "                \n",
    "        unique_names.sort()\n",
    "        return unique_names\n",
    "                \n",
    "            \n",
    "            \n",
    "            \n",
    "                "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        timeMap = defaultdict(list)\n",
    "        for name, time in zip(keyName,keyTime):\n",
    "            hour,minute=int(time[:2]),int(time[3:])\n",
    "            timeMap[name].append(hour*60+minute)\n",
    "        ans=[]\n",
    "        for name, times in timeMap.items():\n",
    "            times.sort()\n",
    "            n=len(times)\n",
    "            for i in range(n-2):\n",
    "                if times[i+2]-times[i]<=60:\n",
    "                    ans.append(name)\n",
    "                    break\n",
    "        ans.sort()\n",
    "        return ans\n",
    "            \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        dic = defaultdict(list)\n",
    "        ans = []\n",
    "        for i in range(len(keyName)):\n",
    "            time = int(keyTime[i][:2]) * 60 + int(keyTime[i][3:])\n",
    "            dic[keyName[i]].append(time)\n",
    "        for j in dic.keys():\n",
    "            if (n := len(dic[j])) >= 3:\n",
    "                dic[j].sort()\n",
    "                for k in range(n-2):\n",
    "                    if dic[j][k+2] - dic[j][k] <= 60:\n",
    "                        ans.append(j)\n",
    "                        break\n",
    "        return sorted(ans)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        dic = defaultdict(list)\n",
    "        ans = []\n",
    "        for i in range(len(keyName)):\n",
    "            time = int(keyTime[i][:2]) * 60 + int(keyTime[i][3:])\n",
    "            dic[keyName[i]].append(time)\n",
    "        for j in dic.keys():\n",
    "            if (n := len(dic[j])) >= 3:\n",
    "                dic[j].sort()\n",
    "                for k in range(n-2):\n",
    "                    if dic[j][k+2] - dic[j][k] <= 60:\n",
    "                        ans.append(j)\n",
    "                        break\n",
    "        return sorted(ans)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        d = defaultdict(list)\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            d[name].append(60 * int(time[0:2])+int(time[3:]))\n",
    "        ans = []\n",
    "        for name, l in d.items():\n",
    "            l.sort()\n",
    "            for i in range(len(l)-2):\n",
    "                if l[i] + 60 >= l[i+2]:\n",
    "                    ans.append(name)\n",
    "                    break\n",
    "        ans.sort()\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        res = []\n",
    "        dic = defaultdict(list)\n",
    "        for i in range(len(keyName)):\n",
    "            dic[keyName[i]].append(int(keyTime[i][:2]) * 60 + int(keyTime[i][3:]))\n",
    "        for name, time in dic.items():\n",
    "            if (n := len(time)) > 2:\n",
    "                time.sort()\n",
    "                for i in range(n-2):\n",
    "                    if time[i+2] - time[i] <= 60:\n",
    "                        res.append(name)\n",
    "                        break\n",
    "        res.sort()\n",
    "        return res\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        timeMap = defaultdict(list)\n",
    "        for name, time in zip(keyName, keyTime):\n",
    "            hour, minute = int(time[:2]), int(time[3:])\n",
    "            timeMap[name].append(hour * 60 + minute)\n",
    "\n",
    "        ans = []\n",
    "        for name, times in timeMap.items():\n",
    "            times.sort()\n",
    "            for i in range(2, len(times)):\n",
    "                if times[i] -times[i-2] <= 60:\n",
    "                    ans.append(name)\n",
    "                    break\n",
    "        ans.sort()\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        d = defaultdict(list)\n",
    "        for name, t in zip(keyName, keyTime):\n",
    "            t = int(t[:2]) * 60 + int(t[3:])\n",
    "            d[name].append(t)\n",
    "        ans = []\n",
    "        for name, ts in d.items():\n",
    "            if (n := len(ts)) > 2:\n",
    "                ts.sort()\n",
    "                for i in range(n - 2):\n",
    "                    if ts[i + 2] - ts[i] <= 60:\n",
    "                        ans.append(name)\n",
    "                        break\n",
    "        ans.sort()\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "\n",
    "        d = defaultdict(list)\n",
    "\n",
    "        for name, t in zip(keyName, keyTime):\n",
    "\n",
    "            t = int(t[:2]) * 60 + int(t[3:])\n",
    "\n",
    "            d[name].append(t)\n",
    "\n",
    "        ans = []\n",
    "\n",
    "        for name, ts in d.items():\n",
    "\n",
    "            if (n := len(ts)) > 2:\n",
    "\n",
    "                ts.sort()\n",
    "\n",
    "                for i in range(n - 2):\n",
    "\n",
    "                    if ts[i + 2] - ts[i] <= 60:\n",
    "\n",
    "                        ans.append(name)\n",
    "\n",
    "                        break\n",
    "\n",
    "        ans.sort()\n",
    "\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        d = defaultdict(list)\n",
    "        for name, t in zip(keyName, keyTime):\n",
    "            t = int(t[:2]) * 60 + int(t[3:])\n",
    "            d[name].append(t)\n",
    "        ans = []\n",
    "        for name, ts in d.items():\n",
    "            if (n := len(ts)) > 2:\n",
    "                ts.sort()\n",
    "                for i in range(n - 2):\n",
    "                    if ts[i + 2] - ts[i] <= 60:\n",
    "                        ans.append(name)\n",
    "                        break\n",
    "        ans.sort()\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        n = len(keyName)\n",
    "        table = defaultdict(list)\n",
    "        def vals(s:str):\n",
    "            a,b = s.split(':')\n",
    "            return int(a)*60+int(b)\n",
    "        for i in range(n):\n",
    "            table[keyName[i]].append(vals(keyTime[i]))\n",
    "        ans = []\n",
    "        for c in table:\n",
    "            table[c].sort()\n",
    "            for i in range(len(table[c])):\n",
    "                t = bisect_right(table[c],table[c][i]+60)\n",
    "                if t-i>=3:\n",
    "                    ans.append(c)\n",
    "        ans = list(set(ans))\n",
    "        ans.sort()\n",
    "        return ans\n",
    "\n",
    "\n",
    "        \n",
    "        \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        d = defaultdict(list)\n",
    "        for name, t in zip(keyName, keyTime):\n",
    "            t = int(t[:2]) * 60 + int(t[3:])\n",
    "            d[name].append(t)\n",
    "        ans = []\n",
    "        for name, ts in d.items():\n",
    "            if (n := len(ts)) > 2:\n",
    "                ts.sort()\n",
    "                for i in range(n - 2):\n",
    "                    if ts[i + 2] - ts[i] <= 60:\n",
    "                        ans.append(name)\n",
    "                        break\n",
    "        ans.sort()\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        user_d = {}\n",
    "        n = len(keyName)\n",
    "        def int_time(time):\n",
    "            hour_,minute_ = time.split(':')\n",
    "            hour_,minute_ = int(hour_),int(minute_)\n",
    "            return hour_*60+minute_\n",
    "        for i in range(n):\n",
    "            if keyName[i] not in user_d:\n",
    "                user_d[keyName[i]] = []\n",
    "            cur_time = int_time(keyTime[i])\n",
    "            user_d[keyName[i]].append(cur_time)\n",
    "            # if cur_time <= 60:\n",
    "                # user_d[keyName[i]].append(cur_time + 24*60)\n",
    "        for name in user_d.keys():\n",
    "            user_d[name].sort()\n",
    "        res = []\n",
    "        for name,lst in user_d.items():\n",
    "            if len(lst) <= 2:\n",
    "                continue\n",
    "            start_idx = 0\n",
    "            start_time = lst[0]\n",
    "            cur_cnt = 1\n",
    "            for t in lst[1:]:\n",
    "                while t - start_time > 60:\n",
    "                    \n",
    "                    start_idx += 1\n",
    "                    # print(lst,t,start_time,start_idx)\n",
    "                    start_time = lst[start_idx]\n",
    "                    cur_cnt -= 1\n",
    "                cur_cnt += 1\n",
    "                # print(f'name = {name},cur_time = {t}, start time = {start_time}, cur cnt = {cur_cnt}')\n",
    "                if cur_cnt == 3:\n",
    "                    # print('hello ?')\n",
    "                    res.append(name)\n",
    "                    break\n",
    "        # print(res)\n",
    "        res.sort()\n",
    "        # print(res)\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        dic = {}\n",
    "        ans = []\n",
    "        for i in range(len(keyName)):\n",
    "            time = int(keyTime[i][:2]) * 60 + int(keyTime[i][3:])\n",
    "            if keyName[i] not in dic.keys():\n",
    "                dic[keyName[i]] = [time]\n",
    "            else:\n",
    "                dic[keyName[i]].append(time)\n",
    "        for j in dic.keys():\n",
    "            if len(dic[j]) >= 3:\n",
    "                dic[j].sort()\n",
    "                for k in range(len(dic[j])-2):\n",
    "                    if dic[j][k+2] - dic[j][k] <= 60:\n",
    "                        ans.append(j)\n",
    "                        break\n",
    "        return sorted(ans)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        def transfer(x):\n",
    "            first=int(x[0:2])\n",
    "            second=int(x[3:5])\n",
    "            value=first*60+second\n",
    "            return value\n",
    "        \n",
    "        ans=[]\n",
    "        \n",
    "        dict1=dict()\n",
    "        for i in range(len(keyTime)):\n",
    "            if keyName[i] not in dict1:\n",
    "                dict1[keyName[i]]=[transfer(keyTime[i])]\n",
    "            else:\n",
    "                dict1[keyName[i]].append(transfer(keyTime[i]))\n",
    "        #return dict1\n",
    "\n",
    "        for i,j in dict1.items():\n",
    "            if len(j)>=3:\n",
    "                j.sort()\n",
    "                for z in range(len(j)-2):\n",
    "                    if j[z+2]-j[z]<=60:\n",
    "                        ans.append(i)\n",
    "                        break\n",
    "        ans.sort()\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "from typing import List\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        name_set = set()  # 用于存储唯一的名称\n",
    "        timeout_set = set()  # 用于存储超时的名称\n",
    "        name_to_times = {}  # 用于将名称映射到时间列表\n",
    "\n",
    "        for i in range(len(keyName)):\n",
    "            name = keyName[i]\n",
    "            time = keyTime[i]\n",
    "            if name not in name_set:\n",
    "                name_set.add(name)\n",
    "                name_to_times[name] = []\n",
    "            name_to_times[name].append(self.parse_time(time))\n",
    "\n",
    "        for name, times in name_to_times.items():\n",
    "            if self.has_alert(name, times):\n",
    "                timeout_set.add(name)\n",
    "\n",
    "        return sorted(list(timeout_set))\n",
    "\n",
    "    def parse_time(self, time_str: str) -> int:\n",
    "        hour, minute = map(int, time_str.split(':'))\n",
    "        return hour * 60 + minute\n",
    "\n",
    "    def has_alert(self, name: str, times: List[int]) -> bool:\n",
    "        times.sort()\n",
    "        for i in range(len(times) - 2):\n",
    "            if times[i + 2] - times[i] <= 60:\n",
    "                return True\n",
    "        return False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def __binary_insert(self, arr, item):\n",
    "        if not arr:\n",
    "            arr.append(item)\n",
    "            return\n",
    "\n",
    "        left, right = 0, len(arr) - 1\n",
    "\n",
    "        while left <= right:\n",
    "            mid = (left + right) // 2\n",
    "            curr = arr[mid]\n",
    "\n",
    "            if curr > item:\n",
    "                right = mid - 1\n",
    "            elif curr <= item:\n",
    "                left = mid + 1\n",
    "                \n",
    "        arr.insert(left, item)\n",
    "\n",
    "\n",
    "    def __isIn1Hour(self, timeA, timeB):\n",
    "        hour_diff = int(timeB[0: 2]) - int(timeA[0: 2])\n",
    "        minute_diff = int(timeB[3: 5]) - int(timeA[3: 5])\n",
    "\n",
    "        if  hour_diff == 0:\n",
    "            return True\n",
    "\n",
    "        if hour_diff >= 2:\n",
    "            return False\n",
    "\n",
    "        return minute_diff <= 0\n",
    "\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        record = {}\n",
    "        n = len(keyName)\n",
    "        max_allowed_times = 3\n",
    "        unique_names = []\n",
    "\n",
    "        sorted_records = sorted(zip(keyName, keyTime), key=lambda x: x[1])\n",
    "\n",
    "        for i in range(n):\n",
    "            name, time = sorted_records[i]\n",
    "\n",
    "            lastRecord = record.get(name)\n",
    "\n",
    "            if not lastRecord:\n",
    "                record[name] = (time, time, 1)\n",
    "                continue\n",
    "            \n",
    "            startTime, lastTime, counter = lastRecord\n",
    "            if counter == max_allowed_times:\n",
    "                continue\n",
    "\n",
    "            if self.__isIn1Hour(startTime, time):\n",
    "                if counter == max_allowed_times - 1:\n",
    "                    self.__binary_insert(unique_names, name)\n",
    "                    record[name] = (startTime, time, max_allowed_times)\n",
    "                else:\n",
    "                    record[name] = (startTime, time, counter + 1)\n",
    "            else:\n",
    "                if self.__isIn1Hour(lastTime, time):\n",
    "                    record[name] = (lastTime, time, 2)\n",
    "                else:\n",
    "                    record[name] = (time, time, 1)\n",
    "                \n",
    "\n",
    "        return unique_names\n",
    "                \n",
    "            \n",
    "            \n",
    "            \n",
    "                "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def __isIn1Hour(self, timeA, timeB):\n",
    "        hour_diff = int(timeB[0: 2]) - int(timeA[0: 2])\n",
    "        minute_diff = int(timeB[3: 5]) - int(timeA[3: 5])\n",
    "\n",
    "        if  hour_diff == 0:\n",
    "            return True\n",
    "\n",
    "        if hour_diff >= 2:\n",
    "            return False\n",
    "\n",
    "        return minute_diff <= 0\n",
    "\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        record = {}\n",
    "        n = len(keyName)\n",
    "        max_allowed_times = 3\n",
    "        unique_names = []\n",
    "\n",
    "        sorted_records = sorted(zip(keyName, keyTime), key=lambda x: x[1])\n",
    "\n",
    "        for i in range(n):\n",
    "            name, time = sorted_records[i]\n",
    "\n",
    "            lastRecord = record.get(name)\n",
    "\n",
    "            if not lastRecord:\n",
    "                record[name] = (time, time, 1)\n",
    "                continue\n",
    "            \n",
    "            startTime, lastTime, counter = lastRecord\n",
    "            if counter == max_allowed_times:\n",
    "                continue\n",
    "\n",
    "            if self.__isIn1Hour(startTime, time):\n",
    "                if counter == max_allowed_times - 1:\n",
    "                    unique_names.append(name)\n",
    "                    record[name] = (startTime, time, max_allowed_times)\n",
    "                else:\n",
    "                    record[name] = (startTime, time, counter + 1)\n",
    "            else:\n",
    "                if self.__isIn1Hour(lastTime, time):\n",
    "                    record[name] = (lastTime, time, 2)\n",
    "                else:\n",
    "                    record[name] = (time, time, 1)\n",
    "                \n",
    "        unique_names.sort()\n",
    "        return unique_names\n",
    "                \n",
    "            \n",
    "            \n",
    "            \n",
    "                "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        name=keyName\n",
    "        time=keyTime\n",
    "        ss = []\n",
    "        for i in range(len(time)):\n",
    "            m, s = time[i].split(\":\")\n",
    "            ss.append(int(m) * 60 + int(s))\n",
    "        mp = zip(name, ss)\n",
    "        mp = sorted(mp)\n",
    "        l = list(mp)\n",
    "        res = []\n",
    "        for i in range(len(l) - 2):\n",
    "            if l[i][0] == l[i + 2][0] and l[i + 2][1] - l[i][1] <= 60:\n",
    "                res.append(l[i][0])\n",
    "    \n",
    "        res = sorted(set(res))\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def __binary_insert(self, arr, item):\n",
    "        if not arr:\n",
    "            arr.append(item)\n",
    "            return\n",
    "\n",
    "        left, right = 0, len(arr) - 1\n",
    "\n",
    "        while left <= right:\n",
    "            mid = (left + right) // 2\n",
    "            curr = arr[mid]\n",
    "\n",
    "            if curr > item:\n",
    "                right = mid - 1\n",
    "            elif curr <= item:\n",
    "                left = mid + 1\n",
    "                \n",
    "        arr.insert(left, item)\n",
    "\n",
    "\n",
    "    def __isIn1Hour(self, timeA, timeB):\n",
    "        hour_diff = int(timeB[0: 2]) - int(timeA[0: 2])\n",
    "        minute_diff = int(timeB[3: 5]) - int(timeA[3: 5])\n",
    "\n",
    "        if  hour_diff == 0:\n",
    "            return True\n",
    "\n",
    "        if hour_diff >= 2:\n",
    "            return False\n",
    "\n",
    "        return minute_diff <= 0\n",
    "\n",
    "    def alertNames(self, keyName: List[str], keyTime: List[str]) -> List[str]:\n",
    "        record = {}\n",
    "        n = len(keyName)\n",
    "        max_allowed_times = 3\n",
    "        unique_names = []\n",
    "\n",
    "        sorted_records = sorted(zip(keyName, keyTime), key=lambda x: x[1])\n",
    "        print(sorted_records)\n",
    "\n",
    "        for i in range(n):\n",
    "            name, time = sorted_records[i]\n",
    "\n",
    "            lastRecord = record.get(name)\n",
    "\n",
    "            if not lastRecord:\n",
    "                record[name] = (time, time, 1)\n",
    "                continue\n",
    "            \n",
    "            startTime, lastTime, counter = lastRecord\n",
    "            if counter == max_allowed_times:\n",
    "                continue\n",
    "\n",
    "            if self.__isIn1Hour(startTime, time):\n",
    "                if counter == max_allowed_times - 1:\n",
    "                    self.__binary_insert(unique_names, name)\n",
    "                    record[name] = (startTime, time, max_allowed_times)\n",
    "                else:\n",
    "                    record[name] = (startTime, time, counter + 1)\n",
    "            else:\n",
    "                if self.__isIn1Hour(lastTime, time):\n",
    "                    record[name] = (lastTime, time, 2)\n",
    "                else:\n",
    "                    record[name] = (time, time, 1)\n",
    "                \n",
    "\n",
    "        return unique_names\n",
    "                \n",
    "            \n",
    "            \n",
    "            \n",
    "                "
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 2
}
